

use std::{rc::Rc, cell::RefCell, ops::Deref, sync::Mutex};

use winit::{event::{ElementState, VirtualKeyCode, MouseButton}, dpi::PhysicalPosition};

use crate::{math::{Vector2f}, config::AliceConfig, function::geometry::rect::Rect};

use super::{converter::{convert_element_state, convert_virtual_key_code, convert_mouse_button}, state::AliceInputState, InputContext, RawInput, KeyCode, Event};


use once_cell::sync::OnceCell;

pub  static mut INPUT:OnceCell<InputImpl> = OnceCell::new();


// #[derive(Clone)]
// pub struct AliceInput(Rc<RefCell<InputImpl>>);

// impl AliceInput {
//     pub fn new(config:&AliceConfig) -> Self {
//         Self(Rc::new(RefCell::new(InputImpl::new(config))))
//     }
//     pub fn begin_frame(&mut self) {
//         self.borrow_mut().begin_frame()
//     }

//     pub fn resize(&mut self) {
//         self.0.borrow_mut().resize()
//     }
// }

// impl Deref for AliceInput {
//     type Target = Rc<RefCell<InputImpl>>;

//     fn deref(&self) -> &Self::Target {
//         &self.0
//     }
// }

// /// handle input
// /// 
// impl AliceInput {
//     pub fn on_key_input(
//         &mut self,
//         state: ElementState,
//         virtual_keycode: Option<VirtualKeyCode>,
//     ) {
//         self.borrow_mut().on_key_input(state, virtual_keycode)
//     }

//     pub fn on_character_input(
//         &mut self,
//         chr:&char
//     ) {
//         self.borrow_mut().on_character_input(chr)
//     }

//     pub fn on_mouse_button_input(
//         &mut self,
//         state: ElementState,
//         button: MouseButton,
//     ) {
//         self.borrow_mut().on_mouse_button_input(state, button)
//     }

//     pub fn on_cursor_moved(&mut self, pos_in_pixels: PhysicalPosition<f64>) {
//         self.borrow_mut().on_cursor_moved(pos_in_pixels)
//     }
// }

/// 
/// key check

// impl AliceInput {
//     pub fn is_key_pressed(&self ,code:KeyCode) -> bool {
//         self.borrow().ctx.keys_down.contains(&code)
//     }

   
// }




pub struct InputImpl {
    pub ctx:InputContext, 
    pub raw_input: RawInput , 
    pub cursor_pos:Option<Vector2f> ,
        // config:    AliceConfig
}

impl InputImpl {
    pub fn new(config:&AliceConfig) -> Self {
        let screen = config.get_window_size();
        Self { ctx: InputContext::new(Vector2f::new(screen.x as f32,screen.y as f32)), raw_input: Default::default(), cursor_pos: None }
    }

    pub fn resize(&mut self, config:&AliceConfig) {
        let screen_size = config.get_screen_size();
        self.raw_input.screen_rect = Some(Rect::from_min_size(
            Default::default(),
            Vector2f::new(screen_size.x as f32,screen_size.y as f32),
        ));
    }

    pub fn on_key_input(
        &mut self,
        state: ElementState,
        virtual_keycode: Option<VirtualKeyCode>,
    ) {
        if let Some(key) = &virtual_keycode {
            let state = convert_element_state(state);
            let key = convert_virtual_key_code(&key);
                self.raw_input.events.push(Event::Key {
                    pressed:state == AliceInputState::Pressed,
                    modifiers: self.raw_input.modifiers,
                    key,
                });
        }
    }

    pub fn on_character_input(
        &mut self,
        chr:&char
    ) {
        if let Some(_pos) = self.cursor_pos {
            let is_mac_cmd = cfg!(target_os = "macos")
            && (self.raw_input.modifiers.ctrl || self.raw_input.modifiers.mac_cmd);

            if is_printable_char(*chr) && !is_mac_cmd {
                self.raw_input.events.push(Event::Text(chr.to_string()));
            } 
               
        }
    }

    pub fn on_mouse_button_input(
        &mut self,
        state: ElementState,
        button: MouseButton,
    ) {
        if let Some(pos) = self.cursor_pos {
                let button = convert_mouse_button(button);
                let state = convert_element_state(state);
             
                self.raw_input.events.push(Event::PointerButton {
                    pos,
                    button,
                    pressed:state == AliceInputState::Pressed,
                    modifiers: self.raw_input.modifiers,
                });
        }
    }

    pub fn begin_frame(&mut self) {
        // input_ctx = std::mem::take(&mut input_ctx).begin_time(input.take());
        self.ctx = std::mem::take(&mut self.ctx).begin_time(self.raw_input.take());
    }

    pub fn on_cursor_moved(&mut self, pos_in_pixels: PhysicalPosition<f64>) {
        self.cursor_pos = Some(Vector2f::new(pos_in_pixels.x as f32,pos_in_pixels.y as f32));
        self.raw_input
        .events
        .push(Event::PointerMoved(self.cursor_pos.unwrap()));
    }

    // pub fn on_ime() => {

    // }
}


impl InputImpl {
        pub fn is_key_pressed(&self ,code:KeyCode) -> bool {
        self.ctx.keys_down.contains(&code)
    }
}


fn is_printable_char(chr: char) -> bool {
    let is_in_private_use_area = '\u{e000}' <= chr && chr <= '\u{f8ff}'
        || '\u{f0000}' <= chr && chr <= '\u{ffffd}'
        || '\u{100000}' <= chr && chr <= '\u{10fffd}';

    !is_in_private_use_area && !chr.is_ascii_control()
}